package com.yao;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.joining;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import com.yao.common.Startup;
import com.yao.entity.Trader;
import com.yao.entity.Transaction;

/**
 * 第五章 - 使用流
 * 
 * @author yaoym
 * @date 2018年1月30日 下午3:18:08
 * @version V1.0
 */
public class SessionFifth {

	static List<Transaction> transactions;

	/**
	 * 数据初始化
	 */
	static {
		transactions = Startup.getTransactions();
	}

	/*(1) 找出2011年发生的所有交易，并按交易额排序（从低到高）。*/
	private static void traningOne(){
		transactions.stream()
		.filter(t -> t.getYear() == 2011)
//		.sorted((t1, t2) -> t1.getValue() - t2.getValue())
		.sorted(comparing(Transaction::getValue))
		.forEach(System.out::println);
	}
	
	/*(2) 交易员都在哪些不同的城市工作过？*/
	private static void traningTwo(){
		transactions.stream()
		.map(t -> t.getTrader().getCity())
		.distinct()
		.forEach(System.out::println);
	}
	
	
	/*(3) 查找所有来自于剑桥的交易员，并按姓名排序。*/
	private static void traningThree(){
//		transactions.stream()
//		.filter(t -> "Cambridge".equalsIgnoreCase(t.getTrader().getCity()))
//		.sorted((t1, t2) -> t1.getTrader().getName().compareToIgnoreCase(t2.getTrader().getName()))
//		.map(t -> t.getTrader())
//		.distinct()
//		.forEach(System.out::println);
		transactions.stream()
		.map(Transaction::getTrader)
		.filter(t -> "Cambridge".equalsIgnoreCase(t.getCity()))
		.distinct()
		.sorted(comparing(Trader::getName))
		.forEach(System.out::println);
	}
	
	/*(4) 返回所有交易员的姓名字符串，按字母顺序排序。 */
	private static void traningFour(){
		String traderStr = transactions.stream()
		.map(t -> t.getTrader().getName())
		.distinct()
		.sorted()
//		.reduce("", (s1, s2) -> s1+s2);
		.collect(joining());
		
		System.out.println(traderStr);
	}
	
	/*(5) 有没有交易员是在米兰工作的？*/
	private static void traningFive(){
		boolean is = transactions.stream()
		.anyMatch(t -> "Milan".equalsIgnoreCase(t.getTrader().getCity()));
		
		System.out.println(is);
	}
	
	/*(6) 打印生活在剑桥的交易员的所有交易额。*/
	private static void traningSix(){
		transactions.stream()
		.filter(t -> "Cambridge".equalsIgnoreCase(t.getTrader().getCity()))
		.map(Transaction::getValue)
		.forEach(System.out::println);
	}
	
	/*(7) 所有交易中，最高的交易额是多少？*/
	private static void traningSeven(){
		transactions.stream()
		.map(Transaction::getValue)
		.reduce(Integer::max)
		.ifPresent(System.out::println);
	}
	
	/*(8) 找到交易额最小的交易。*/
	private static void traningEight(){
//		transactions.stream()
//		.reduce( (t1, t2) -> t1.getValue() > t2.getValue() ? t1 : t2)
//		.ifPresent(System.out::println);
		
		transactions.stream()
		.min(comparing(Transaction::getValue))
		.ifPresent(System.out::println);
	}
	
	
	/*数值流应用：求勾股数*/
	private static void traningNigth(){
		// a*a + b*b = c*c
		
//		int a = 5;
//		IntStream.rangeClosed(1, 50)
//		.filter(b -> Math.sqrt(a*a+ b*b) % 1 == 0)
//		.mapToObj(b -> new int[]{a, b, (int)Math.sqrt(a*a+ b*b)})
//		.forEach(t -> System.out.println(t[0]+","+t[1]+","+t[2]));;
		
		//1.
		Stream<double[]> pythagoreanTriples = IntStream.rangeClosed(1, 50).boxed()
				.flatMap(a -> IntStream.rangeClosed(a, 50)
						.filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
						.mapToObj(b -> new double[] { a, b, Math.sqrt(a * a + b * b) }));
				
		//2.
		pythagoreanTriples = IntStream.rangeClosed(1, 50).boxed()
				.flatMap(a -> IntStream.rangeClosed(a, 50)
						.mapToObj(b -> new double[]{a, b, Math.sqrt(a * a + b * b)})
						.filter(c -> c[2] % 1 == 0));
		
		//输出结果
		pythagoreanTriples.forEach(t -> System.out.println(t[0] + "," + t[1] + "," + t[2]));
		System.out.println();
	}
	
	
	/*由值创建流*/
	private static void traningTen(){
		Stream<String> strStream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
		strStream = strStream.map(s -> s.toUpperCase());
		strStream.forEach(System.out::println);
	}
	
	/*5.7.4 由函数生成流：创建无限流*/
	private static void traningEleven(){
		/*Stream.iterate  按顺序生成无限流*/
		Stream.iterate(2, n -> n + 2).limit(5).forEach(System.out::println);
		
		System.out.println("斐波纳契输出前20个数：");
		//斐波纳契
		//0,1,1,2,3,5,8... 后续的每个数等于前两个数之和
		/*Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0]+n[1]})
		.limit(20)
		.forEach(t -> System.out.println("(" + t[0] + "," + t[1] +")")); */

		Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0]+n[1]})
		.limit(20)
		.map(n -> n[0])
		.forEach(System.out::println);
		
		
		/*Stream.generate */
		Stream.generate(Math::random)
		.limit(5)
		.forEachOrdered(System.out::println);
	}
	
	
	
	public static void main(String[] args) {
		System.out.println("(1) 找出2011年发生的所有交易，并按交易额排序（从低到高）。");
		traningOne();

		System.out.println("(2) 交易员都在哪些不同的城市工作过？");
		traningTwo();

		System.out.println("(3) 查找所有来自于剑桥的交易员，并按姓名排序。");
		traningThree();

		System.out.println("(4) 返回所有交易员的姓名字符串，按字母顺序排序。");
		traningFour();

		System.out.println("(5) 有没有交易员是在米兰工作的？");
		traningFive();

		System.out.println("(6) 打印生活在剑桥的交易员的所有交易额。");
		traningSix();
		
		System.out.println("(7) 所有交易中，最高的交易额是多少？");
		traningSeven();
		
		System.out.println("(8) 找到交易额最小的交易。");
		traningEight();
		
		System.out.println("数值流应用：求勾股数");
		traningNigth();
		
		traningTen();
		
		System.out.println("5.7.4 由函数生成流：创建无限流");
		traningEleven();
		
		Stream<int[]> i = Stream.of(new int[]{1,2,3}, new int[]{1,2,3});
//		i.forEach(a -> System.out.println(a[0]+ " - " +a[1]));
		
		
		try {
			Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
			
//			lines.forEach(System.out::println);
			
			lines.flatMap(line -> Arrays.stream(line.split(" ")))
			.distinct()
//			.count()
			.forEach(System.out::println);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
